package net.hyperz.hackit.util;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

@SuppressWarnings("unused")
public class DBProvider {
	private static final String DATABASE_NAME = "hackit.db";
	private static final int DATABASE_VERSION = 1;
	
	private static final String TAG = "DBProvider";
	
	private Context ctx = null;
	private SQLiteDatabase DBInstance;
	
	private static enum Table {
		PROCESS(0, "Process"),
		PROGRAM(1, "Program"),
		RIG(2, "Rig"),
		SKILLSET(3, "SkillSet"),
		SOLARCELLS(4, "SolarCells"),
		TYPE(5, "Type"),
		USER(6, "User");
		
		private final int Index;
		private final String Name;
		
		private Table(int index, String tableName) { 
			Index = index; 
			Name = tableName;
		}
		
		public int getIndex() {
			return Index;
		}
		
		public String getName() {
			return Name;
		}
	}
	
	public DBProvider(Context context) {
		ctx = context;
	}
	
	//---opens the database---
	public DBProvider open() throws SQLException 
	{
		boolean getDatabase = false;
		
		try {
			OpenHelper oh = new OpenHelper(this.ctx);
			if (DBInstance == null) {
					getDatabase = true;
			} else {
				if (!DBInstance.isOpen()) {
					getDatabase = true;
				}
			}
			
			if (getDatabase) {
				DBInstance = oh.getWritableDatabase();
				DBInstance.setLockingEnabled(false);
			}
			
			return this;
		}
		catch (SQLiteException sqlE) {
			Log.e(TAG, "SQLLiteException", sqlE);
			return null;
		}
		catch (Exception ex) {
			Log.e(TAG, "SQLLiteException", ex);
			return null;
		}
	}
	
	//---closes the database---
	public void close() 
	{
		if (DBInstance != null) {
			if (DBInstance.isOpen()) {
				SQLiteDatabase.releaseMemory();
				DBInstance.close();
			}
		}
	}
	
	private class OpenHelper extends SQLiteOpenHelper {
		public OpenHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}
		
		@Override
		public void onOpen(SQLiteDatabase dbInstance) {
			dbInstance.setVersion(DATABASE_VERSION);
		}
		
		//Create all the tables
		@Override
		public void onCreate(SQLiteDatabase dbInstance) {
			//Table: SkillSet
			dbInstance.execSQL("CREATE TABLE SkillSet ( " + 
					"    ID           INTEGER PRIMARY KEY ON CONFLICT FAIL AUTOINCREMENT," + 
					"    Architecture INTEGER NOT NULL ON CONFLICT FAIL," + 
					"    Programming  INTEGER NOT NULL ON CONFLICT FAIL," + 
					"    Networking   INTEGER NOT NULL ON CONFLICT FAIL," + 
					"    Security     INTEGER NOT NULL ON CONFLICT FAIL," + 
					"    Technical    INTEGER NOT NULL ON CONFLICT FAIL " + 
					");");
			
			//Table: SolarCells
			dbInstance.execSQL("CREATE TABLE SolarCells ( " +
					"    ID           INTEGER PRIMARY KEY ON CONFLICT FAIL AUTOINCREMENT," +
					"    CellCount    INTEGER NOT NULL ON CONFLICT FAIL," +
					"    ReservePower REAL    NOT NULL ON CONFLICT FAIL DEFAULT ( 0 )," +
					"    EarnedPower  REAL    NOT NULL ON CONFLICT FAIL DEFAULT ( 0 ) " +
					");");
			
			//Table: User
			dbInstance.execSQL("CREATE TABLE User ( " +
					"    ID          INTEGER PRIMARY KEY ON CONFLICT FAIL AUTOINCREMENT," +
					"    Name        TEXT    NOT NULL ON CONFLICT FAIL," +
					"    Credits     REAL    NOT NULL ON CONFLICT FAIL DEFAULT ( 1500 )," +
					"    SkillSetID  INTEGER NOT NULL ON CONFLICT FAIL," +
					"    TypeID      INTEGER NOT NULL ON CONFLICT FAIL," +
					"    SolarCellID INTEGER REFERENCES SolarCells ( ID )" +
					");");
			
			//Table: Rig
			dbInstance.execSQL("CREATE TABLE Rig ( " +
					"    ID        INTEGER        PRIMARY KEY ON CONFLICT FAIL AUTOINCREMENT," +
					"    UserID    INTEGER        REFERENCES User ( ID )," +
					"    CPU       REAL           NOT NULL ON CONFLICT FAIL," +
					"    RAM       REAL           NOT NULL ON CONFLICT FAIL," +
					"    SSD       REAL           NOT NULL ON CONFLICT FAIL," +
					"    Bandwidth REAL           NOT NULL ON CONFLICT FAIL," +
					"    AdminPass VARCHAR( 50 ) " +
					");");
			
			//Table: Process
			dbInstance.execSQL("CREATE TABLE Process ( " +
					"    ID        INTEGER PRIMARY KEY ON CONFLICT FAIL AUTOINCREMENT," +
					"    ProgramID INTEGER REFERENCES Program ( ID )," +
					"    StartTime DATE    NOT NULL ON CONFLICT FAIL," +
					"    EndTime   DATE," +
					"    OwnerID   INTEGER," +
					"    RigID     INTEGER REFERENCES Rig ( ID ) " +
					");");
			
			//Table: Program
			dbInstance.execSQL("CREATE TABLE Program (" +  
					"    ID       INTEGER        PRIMARY KEY ON CONFLICT FAIL AUTOINCREMENT," +
					"    Name     VARCHAR( 50 )  NOT NULL ON CONFLICT FAIL," +
					"    CPUUsage REAL           NOT NULL ON CONFLICT FAIL," +
					"    RAMUsage REAL           NOT NULL ON CONFLICT FAIL," +
					"    SSDUsage REAL           NOT NULL ON CONFLICT FAIL," +
					"    BWUsage  REAL," +
					"    TypeID   INTEGER        REFERENCES Type ( ID )" +
					");");
			
			//Table: Type
			dbInstance.execSQL("CREATE TABLE Type ( " +
					"    ID          INTEGER         PRIMARY KEY ON CONFLICT FAIL AUTOINCREMENT," +
					"    Name        VARCHAR( 50 )   NOT NULL ON CONFLICT FAIL," +
					"    Description VARCHAR( 255 ) " +
					");");
			
			SQLiteDatabase.releaseMemory();
		}
		
		@Override
		public void onUpgrade(SQLiteDatabase dbInstance, int oldVersion, int newVersion) {
			//for now just drop and recreate!
			//TODO: A proper DB upgrade, involving from which version the upgrade is being 
			// performed from and which database version it's being upgraded too.
			switch (oldVersion) {
			case 1:
			default:
				//drop all the tables defined
				for (Table value : Table.values()) {
					dbInstance.execSQL("DROP TABLE IF EXISTS " + value.getName()); 
				}
				//create a new database
				onCreate(dbInstance);
				break;
			}
			
			SQLiteDatabase.releaseMemory();
		}
	}
	
	
	//---checks if the cursor is not null and moves to first record
	public boolean isValidCursor(Cursor cur) {
		if (cur != null) {
			if (cur.moveToFirst()) {
				return true;
			}
		}
		
		return false;
	}
	
	public int update(String tableName, ContentValues values, String whereClause, String... whereArgs) {
		return DBInstance.update(tableName, values, whereClause, whereArgs);
	}
	
	public long insert(String tableName, ContentValues values) {
		return DBInstance.insert(tableName, null, values);
	}
	
	public int delete(String tableName, String whereClause, String... whereArgs) {
		return DBInstance.delete(tableName, whereClause, whereArgs);
	}
	
	public Cursor select(String query, String[] queryArgs) {
		return DBInstance.rawQuery(query, queryArgs);
	}
}
